<template>
    <div class="icons-container" w-full h-full>
        <div class="icons-grid" h-full>
            <ul class="icons-wrap" h-full w-full>
                <li class="icons-item" h-full w-full :style="{ transform: `translateY(${(index + scrollIndex) * 100}%)` }"
                    v-for="(item, index) in iconsLiList" :key="item.id">
                    <div class="icons-item-content" h-full w-full>
                        <ul class="app-grid">
                            <li v-for="app in item.appList" :key="app.id" class="app-item"
                                @click="handleClickApp(app)"
                                :class="{ 'icon-size-1x1': app.size == '1x1', 'icon-size-1x2': app.size == '1x2', 'icon-size-2x1': app.size == '2x1', 'icon-size-2x2': app.size == '2x2', 'icon-size-2x4': app.size == '2x4' }">
                                <div class="app-item-icon" :class="{ 'swing': globalStore.batchEditFlag}" h-full w-full :id="app.id"
                                    @contextmenu.stop.native="showIconsContextMenu($event,app)" :title="app.name">
                                    <img :src="app.iconImg" alt="" v-if="app.type == 'iframe'" :id="app.id" :style="{ backgroundColor: app.bgColor}" @click="showIframeModal(app.iframeUrl as string)">
                                    <div class="app-item-icon-text flex-center" h-full w-full
                                        :style="{ background: app.bgColor }" v-if="app.type == 'app'" :id="app.id">
                                        <span :id="app.id"
                                            :style="{ transform: app.size !== '1x1' ? 'scale(0.94)' : app.iconText?.substring(0, 3).length == 3 ? `scale(calc(${globalStore.sidebar.iconSize - 10}/(3*22)))` : 'scale(0.94)' }">{{
                                                app.iconText?.substring(0, 3) }}</span>
                                    </div>
                                    <component :is="globalStore.componentList[app.component as string]" :id="app.id" :size="app.size" v-if="app.type == 'component'"></component>
                                </div>
                                <div class="close-icon flex-center" v-show="globalStore.batchEditFlag" @click.stop="globalStore.removeGroupApp(app)">
                                    <el-icon size="12">
                                        <Close />
                                    </el-icon>
                                </div>
                                <p class="app-item-title text-omit" v-show="globalStore.showAppName">{{ app.name }}</p>
                            </li>
                        </ul>
                    </div>
                </li>
            </ul>
        </div>
        <ContextMenu ref="contextMenuRef" v-show="globalStore.contextmenuType == 'icons'">
            <template #li>
                <li class="d-contextmenu-item-app" @click="openToNewTab" v-show="selectIconInfo.type !== 'iframe'">
                    <el-icon size="15" mr8>
                        <Position />
                    </el-icon>
                    <p>在新标签页打开</p>
                </li>
                <li class="d-contextmenu-item-layout">
                    <div class="layout-header">
                        <el-icon size="15" mr8>
                            <Connection />
                        </el-icon>
                        <p>布局</p>
                    </div>
                    <div class="layout-content">
                        <p :class="{ 'active': selectIconInfo.size == '1x1' }" @click="setAppSize('1x1')">1x1</p>
                        <p :class="{ 'active': selectIconInfo.size == '1x2' }" @click="setAppSize('1x2')">1x2</p>
                        <p :class="{ 'active': selectIconInfo.size == '2x1' }" @click="setAppSize('2x1')">2x1</p>
                        <p :class="{ 'active': selectIconInfo.size == '2x2' }" @click="setAppSize('2x2')">2x2</p>
                        <p :class="{ 'active': selectIconInfo.size == '2x4' }" @click="setAppSize('2x4')">2x4</p>
                    </div>
                </li>
                <li class="d-contextmenu-item-app" @click="showEditIconModal(deepCopy(selectIconInfo) as AppListType)">
                    <el-icon size="15" mr8>
                        <Edit />
                    </el-icon>
                    <p>编辑</p>
                </li>
                <li class="d-contextmenu-item-app" @click.stop="batchEdit">
                    <el-icon size="15" mr8>
                        <Files />
                    </el-icon>
                    <p>批量编辑</p>
                </li>
                <li class="d-contextmenu-item-app" @click="deleteApp">
                    <el-icon size="15" mr8>
                        <Delete />
                    </el-icon>
                    <p>删除</p>
                </li>
            </template>
        </ContextMenu>
        <EditIcons ref="editIconsRef" />
        <ShowIframe ref="iframeRef"/>
    </div>
</template>

<script setup lang="ts">
import { Position, Connection, Edit, Files, Delete, Close } from '@element-plus/icons-vue'
import { AppListType } from '@/store/interface/global';
import { useGlobalStore } from '@/store/module/global'
import { debounce } from 'lodash'
import ContextMenu from './contextMenu.vue';
import { useContextMenu, useEditIconModal, useIframeModal } from '@/components/modal';
import EditIcons from '@/components/modal/components/editIcons.vue'
import ShowIframe from '@/components/modal/components/show/iframeModal.vue'

const globalStore = useGlobalStore()
const iconsLiList = computed(() => globalStore.sidebar.groupList)

const {
    contextMenuRef,
    showContextMenu,
    closeContextMenu
} = useContextMenu()

const showIconsContextMenu = (e: any,app: AppListType) => {
    initReactive(selectIconInfo)
    setReactive(selectIconInfo, app)
    globalStore.setContextmenuType('icons')
    showContextMenu(e)
}
const selectIconInfo = reactive<Partial<AppListType>>({})

//新标签页打开
const openToNewTab = () => {
    handleClickApp(selectIconInfo)
}

//布局
const setAppSize = (size: "1x1" | '1x2' | '2x1' | '2x2' | "2x4") => {
    selectIconInfo.size = size
    globalStore.updateGroupApp(deepCopy(selectIconInfo) as AppListType)
}

//删除
const deleteApp = () => {
    globalStore.removeGroupApp(deepCopy(selectIconInfo) as AppListType)
}

//编辑
const {
    editIconsRef,
    showEditIconModal
} = useEditIconModal()

//批量编辑
const batchEdit = () => {
    globalStore.setBatchEditFlag(true)
    closeContextMenu()
}

//iframe弹窗
const {
    iframeRef,
    showIframeModal
} = useIframeModal()

//滚动切换tab
const scrollIndex = ref(0)
const TRANSTYLE = 'transform ease-out .28s'
const transitionStyle = ref(TRANSTYLE)
const handleScroll = debounce((e: WheelEvent) => {
    if (e.deltaY > 0) {
        if (-1 * scrollIndex.value == iconsLiList.value.length - 1) {
            scrollIndex.value = 0
            transitionStyle.value = 'none'
            setTransitionStyle()
            return
        }
        scrollIndex.value--
    } else {
        if (scrollIndex.value == 0) {
            scrollIndex.value = (iconsLiList.value.length - 1) * -1
            transitionStyle.value = 'none'
            setTransitionStyle()
            return
        }
        scrollIndex.value++
    }
    transitionStyle.value = TRANSTYLE
    setTransitionStyle()
}, 100)

const setTransitionStyle = () => {
    arr.forEach.call(iconItemDoms, (item, index) => {
        if (index == 0 || index == iconItemDoms.length - 1)
            item.style.setProperty('transition', TRANSTYLE)
        else
            item.style.setProperty('transition', transitionStyle.value)
    })
    globalStore.sidebar.activeFlag = iconsLiList.value[-scrollIndex.value].id
    globalStore.sidebar.currentTab = scrollIndex.value * -1
}

//监听侧边栏点击，切换tab
const iconItemDoms = document.getElementsByClassName('icons-item')
const arr: any[] = []
watch(() => globalStore.sidebar.currentTab, (newValue, oldValue) => {
    const num = newValue - oldValue
    arr.forEach.call(iconItemDoms, (item, index) => {
        if (num > 0) {
            if (index > oldValue && index < newValue) {
                item.style.setProperty('transition', 'none')
            } else {
                item.style.setProperty('transition', TRANSTYLE)
            }
        } else {
            if (index > newValue && index < oldValue) {
                item.style.setProperty('transition', 'none')
            } else {
                item.style.setProperty('transition', TRANSTYLE)
            }
        }
    })
    scrollIndex.value = newValue * -1
})

onMounted(() => {
    addlistenerWidth()
})

const maxAppWidth = computed(() => globalStore.sidebar.appGridWidth)
const minAppWidth = computed(() => globalStore.sidebar.appGridWidth - 200)
const maxIconWidth = computed(() => globalStore.iconComputedSize)
const minIconWidth = computed(() => globalStore.iconComputedSize - 12)
const maxIconRadius = computed(() => globalStore.iconComputedRadius)
const maxIconGap = computed(() => globalStore.iconComputedGap)
/**监听视口宽度变化，动态计算图标和间距大小
 * 1.间距大小为图标大小的二分之一
 * 2.图标最大为maxIconWidth,最小为minIconWidth
 * 3.设置两个交点(maxIconWidth,maxAppWidth),(minIconWidth,minAppWidth)
 * 4.ax+b=y
 **/
const addlistenerWidth = () => {
    const appGrid = document.querySelector('.icons-grid')
    const ObResize = new ResizeObserver(entries => {
        const a = (maxAppWidth.value - minAppWidth.value) / (maxIconWidth.value - minIconWidth.value)
        const b = maxAppWidth.value - maxIconWidth.value * a
        const width = entries[0].target.clientWidth
        if(width < maxAppWidth.value){
            let iconWidth = (width - b) / a
            if (iconWidth < minIconWidth.value)
                iconWidth = minIconWidth.value
            let radius = maxIconRadius.value * iconWidth / maxIconWidth.value
            let gap = maxIconGap.value * iconWidth / maxIconWidth.value
            globalStore.setIconSize(iconWidth)
            globalStore.setIconRadius(radius)
            globalStore.setIconGap(gap)
        }else{
            globalStore.setIconSize(maxIconWidth.value)
            globalStore.setIconRadius(maxIconRadius.value)
            globalStore.setIconGap(maxIconGap.value)
        }
    })
    ObResize.observe(appGrid as Element)
}

const handleClickApp = (app: Partial<AppListType>) => {
    if (app.type == 'app')
        window.open(app.url)
}

defineExpose({
    handleScroll
})
</script>

<style scoped lang="scss">
.icons-container {
    .icons-grid {
        margin: 0 auto;
        max-width: var(--appGridWidth);
        padding: 0 var(--sideBarWidth, 45px);
        overflow: hidden
    }

    .icons-wrap {
        list-style: none;
        position: relative;
    }

    .icons-item {
        position: absolute;
        top: 0;
        left: 0;
        overflow: auto;

        &::-webkit-scrollbar{
            width: 0;
        }
        //transition: transform ease-out .28s;
    }

    .app-grid {
        padding-top: 2vh;
        padding-bottom: 5rem;
        display: grid;
        grid-template-columns: repeat(auto-fill, var(--iconSize));
        gap: var(--icon-gap-x) var(--icon-gap-y);
        grid-auto-flow: dense;
        opacity: var(--appOpacity);

       @include response(phone){
            padding-top: 0;
        }

    }

    .app-item {
        color: var(--icon-title);
        transition: all .2s;
        position: relative;


        .app-item-icon {
            cursor: pointer;
            border-radius: var(--iconRadius);
            overflow: hidden;

            &:hover {
                box-shadow: 0.3rem 0.3rem 1.5rem rgba(black, .3);
            }

            img{
                border-radius: var(--iconRadius);
                height: 100%;
                width: 100%;
            }
        }

        .app-item-icon-text {
            border-radius: var(--iconRadius);
            font-size: 22px;
            white-space: nowrap;
            overflow: hidden;

            span {
                display: inline-block;
                font-weight: 500;
            }
        }

        .app-item-title {
            width: calc(100% + var(--icon-gap-x));
            margin-left: calc(var(--icon-gap-x)/2*-1);
            text-align: center;
            line-height: 1.1;
            margin-top: 6px;
            font-size: var(--appFontSize);
            color: var(--appFontColor);
        }

        .close-icon {
            height: 20px;
            width: 20px;
            border-radius: 50%;
            cursor: pointer;
            position: absolute;
            right: 2px;
            top: -5px;
            backdrop-filter: blur(10px);
            background-color: #fff6;
            z-index: 10;

            :deep(.el-icon) {
                --color: black;
            }

            &:hover {
                background-color: #d83030;

                .app-item-icon  {
                    pointer-events: none;
                }

                :deep(.el-icon) {
                    --color: white;
                }
            }
        }
    }

    .swing{
        animation: swing .3s ease infinite;
        transform-origin: center 50px;
    }

    @keyframes swing {
        0%{
            transform: rotate(0deg);
        }
        20%{
            transform: rotate(-2deg);
        }
        60%{
            transform: rotate(0deg);
        }
        80%{
            transform: rotate(2deg);
        }
        100%{
            transform: rotate(0deg);
        }
    }

    .icon-size-1x1 {
        width: var(--iconSize);
        height: var(--iconSize);
    }

    .icon-size-1x2 {
        width: calc(var(--iconSize)*2 + var(--icon-gap-x));
        height: var(--iconSize);
        grid-column: span 2;
    }

    .icon-size-2x1 {
        width: var(--iconSize);
        height: calc(var(--iconSize)*2 + var(--icon-gap-x));
        grid-row: span 2;
    }

    .icon-size-2x2 {
        width: calc(var(--iconSize)*2 + var(--icon-gap-x));
        height: calc(var(--iconSize)*2 + var(--icon-gap-x));
        grid-column: span 2;
        grid-row: span 2;
    }

    .icon-size-2x4 {
        width: calc(var(--iconSize)*4 + var(--icon-gap-x)*3);
        height: calc(var(--iconSize)*2 + var(--icon-gap-x));
        grid-column: span 4;
        grid-row: span 2;
    }
}
</style>